#include "non_threshold_evaluator.h"

#include <fstream>
using namespace std;

double graph_based_evaluator::evaluate (vector<int> & label_list, vector<double> & score_list, string output, int bin) {
	int l = (int) label_list.size();

	int tp = 0, tn = 0, fp = 0, fn = 0;
	for(int i = 0; i < l; i++) {
		if(label_list[i] == 1) {
			fn ++;
		} else {
			tn ++;
		}
	}

	threshold_evaluator * x = get_x_evaluator();
	threshold_evaluator * y = get_y_evaluator();

	vector<double> x_list;
	vector<double> y_list;
	
	x_list.push_back(x->get_value(tp, tn, fp, fn));
	y_list.push_back(y->get_value(tp, tn, fp, fn));

	for(int i = 0; i < l; i++) {
		if(label_list[i] == 1) {
			tp ++;
			fn --;
		} else {
			fp ++;
			tn --;
		}
		x_list.push_back(x->get_value(tp, tn, fp, fn));
		y_list.push_back(y->get_value(tp, tn, fp, fn));
	}

	vector<double> bin_list;
	vector<int> count_list;
	bin_list.resize(bin);
	count_list.resize(bin);
	for(unsigned i = 0; i < bin_list.size(); i++) {
		bin_list[i] = 0;
	}

	for(unsigned i = 0; i < x_list.size(); i++) {
		int xb = (int) (x_list[i] * bin);
		if(xb == bin) {
			xb --;
		}

		bin_list[xb] += y_list[i];
		count_list[xb] ++;
	}

	for(unsigned i = 0; i < bin_list.size(); i++) {
		if(count_list[i] != 0) {
			bin_list[i] /= count_list[i];
		}
	}

	ofstream fout(output.c_str());
	fout << x->get_name() << "\t" << y->get_name() << endl;
	for(unsigned i = 0; i < bin_list.size(); i++) {
		fout << i / (double)bin << "\t" << bin_list[i] << endl;
	}
	fout.close();

	delete x;
	delete y;

	double integ = 0;
	for(unsigned i = 0; i < bin_list.size(); i++) {
		integ += bin_list[i];
	}
	integ /= bin_list.size();
	return integ;
}

threshold_evaluator * avg_prec_evaluator::get_x_evaluator() {
	return new precision();
}

threshold_evaluator * avg_prec_evaluator::get_y_evaluator() {
	return new recall();
}

threshold_evaluator * fpr_fnr_evaluator::get_x_evaluator() {
	return new fpr();
}

threshold_evaluator * fpr_fnr_evaluator::get_y_evaluator() {
	return new fnr();
}

non_threshold_evaluator * get_non_threshold_evaluator(string type) {
	non_threshold_evaluator * result = NULL;
	if(type.compare("avg_prec") == 0) {
		result = new avg_prec_evaluator();
	} else if(type.compare("fpr_fnr") == 0) {
		result = new fpr_fnr_evaluator();
	} else if(type.compare("avep") == 0) {
		result = new average_precision_evaluator();
	}

	return result;
}
